/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package computing;

import com.jme3.math.Vector3f;
import data.Vector3i;
import exception.WaypointsNotFoundException;
import java.util.ArrayList;

/**
 *
 * @author oxplay
 */
    public class MakeWaypointsProgressing {

        private ArrayList<Vector3f> waypoints = new ArrayList<Vector3f>();
        private Vector3f from;
        private Vector3f to;
        private boolean useSimulation;
        private boolean useCalculations;
        private int steps;
        private ComputeBlindMove computeBlindMove;
        private ComputeWaypoints computeWaypoints;
        private Vector3i lastWaypoint;
        private Vector3i catchStart;
        private Vector3i catchEnd;
        private boolean isDone = false;
        private EasyFind easyfind;
        
        public MakeWaypointsProgressing(EasyFind easyfind, Vector3f from, Vector3f to, boolean useSimulation, boolean useCalculations, int steps) throws WaypointsNotFoundException {
            this.easyfind = easyfind;
            this.from = from;
            this.to = to;
            this.useSimulation = useSimulation;
            this.useCalculations = useCalculations;
            this.steps = steps;
            this.catchStart = easyfind.grid.getCatchPoint(new Vector3i(from), easyfind.seekCatchPointRange);
            this.catchEnd = easyfind.grid.getCatchPoint(new Vector3i(to), easyfind.seekCatchPointRange);
            if (catchStart == null) {
                throw new WaypointsNotFoundException("initializing", from);
            }
            if (catchEnd == null) {
                throw new WaypointsNotFoundException("initializing", to);
            }
            lastWaypoint = catchStart;
            if (useSimulation) {
                computeBlindMove = new ComputeBlindMove(easyfind.grid, catchStart, catchEnd);
            }
        }

        private boolean updateBlindMove() {
            if (computeBlindMove != null) {
                if (!computeBlindMove.isDone()) {
                    computeBlindMove.makeSteps(steps);
                }
                if (computeBlindMove.isDone()) {
                    waypoints.addAll(computeBlindMove.getWaypoints());
                    Vector3f lastWaypoint3f = computeBlindMove.getLastWaypoint();
                    if (lastWaypoint3f != null) {
                        lastWaypoint = new Vector3i(lastWaypoint3f);
                    }
                    computeBlindMove = null;
                    return true;
                } else {
                    return false;
                }
            } else {
                return true;
            }
        }

        private boolean updateCalculations() throws WaypointsNotFoundException {
            if (useCalculations && (lastWaypoint.x != catchEnd.x || lastWaypoint.y != catchEnd.y || lastWaypoint.z != catchEnd.z)) {
                if(computeWaypoints == null){
                    computeWaypoints = new ComputeWaypoints(easyfind.grid, lastWaypoint, catchEnd, easyfind.calculationsOffset);
                }
                computeWaypoints.update(steps);
                if(computeWaypoints.isDone()){
                    waypoints.addAll(computeWaypoints.getWaypoints());
                    return true;
                } else {
                    return false;
                }
            } else {
                return true;
            }
        }

        public void update() throws WaypointsNotFoundException {
            boolean blindState = updateBlindMove();
            if (blindState) {
                boolean calcState = updateCalculations();
                if (calcState) {
                    isDone = true;
                }
            }
        }

        public boolean isDone() {
            return isDone;
        }

        public ArrayList<Vector3f> getWaypoints() {
            return waypoints;
        }
    }
